/*
 * Test.cpp
 *
 * Created 9/22/2008 By Johnny Huynh
 *
 * Version 00.00.01 11/30/2008
 *
 * Copyright Information:
 * All content copyright © 2008 Johnny Huynh. All rights reserved.
 */
 
 //#define TEST
 
 #ifndef TEST
 #include "Physics.h"
 #include "OpenGL_Headers.h"
 #include "GL_MobileObject.h"
 #include "OBBTree.h"
 #include "InterfaceModule.h"
 #include "Matrix.h"
 #include "GL_Triangle.h"
 #include <vector>
 #include "OrientationMatrix.h"
 #include "GL_MobileObject.h"
 #endif // TEST

 #ifdef TEST
 inline bool compare( int p1, int p2 )
 {
    return p1 < p2;
 }
 #include <vector>
 #include <list>
 #include "Sort.h"
 #include <iostream>
 #include "introsort.h"
 #include "smoothsort.h"
 #include "advance_sort.h"
 #include "Vector3.h"
 #include "OrientationMatrix.h"
 #include "GL_MobileObject.h"
 #include "Algebra3.h"
 #endif // TEST
 
template<typename T>
bool compareTest( bool(**compare)(T, T), size_t size )
{
    for ( int i = 0; i < size; ++i )
    {
        std::cout << compare[i]( 2, 2 ) << std::endl;
        if ( !compare[i]( 2, 2 ) )
            return false;
    }
    
    return true;
}

template <typename TYPENAME>
inline float test1()
{
    return 1.0f;
}

template <typename TYPENAME>
inline void test2()
{

}

template <typename TYPENAME>
inline TYPENAME my_fabs( const TYPENAME& a )
{
    return -1 * a;
}

int main( int argc, char* argv[] )
{
/*
    const GLdouble velocity[3] = { 0.0, 0.0, 0.0 };
    const GLdouble center[3] = { 0, 0, 0 };
    HitBox hb( 2.5, 1.5, 1.0, velocity, center  );
    hb.isInsideOBB( Vector3f( 0, 0, 0 ) );
    system("PAUSE");*/
    #ifndef TEST
    initializeMobj();
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
    
    // Either enterWindowMode or enterFullScreenMode, but not both
    if ( isGameMode )
        enterFullScreenMode();
    else
        enterWindowMode();

    glutMainLoop();
    #endif
    
    /*
    Vector3f a( 1, 0, 0 );
    Vector3f b( 0, 1, 0 );
    Vector3f c( 0, 0, 1 );
    Triangle<GLfloat> tri(a, b, c);
    print(tri);
    printf("Triangle Area: %1f\n", area( tri ));
    
    Vector3f vec( 2, 3, 1 );
    Vector3f newvec = vec.getNormal();
    print( vec );
    print( newvec );
    Matrix3f mat( 1, 2, 3, 
                  3, 2, 1, 
                  0, 0, 0 );
    Matrix3f inverseMat = mat.getInverse();
    print( mat );
    print(inverseMat);
    print(mat * inverseMat);
    printf("size: %1d\n", sizeof(GLfloat));
    GL_Trianglef gl_tri( tri );
    GL_Trianglef gl_tri2( a, b, c );
    print( gl_tri );
    print( normal( gl_tri2 ) );
    
    int t = 5;
    int u = 60;
    int v = 11;
    std::vector< int > integers;
    integers.push_back( t );
    integers.push_back( u );
    integers.push_back( v );

    std::vector< int > integers2;
    integers2.insert( integers2.begin(), integers.begin(), integers.end() );
    //integers2.reserve( integers.size() );
    //memcpy( &integers2, &integers, sizeof(integers) );
    //std::copy( &integers[0], &integers[2] + 1, std::back_inserter( integers2 ) );

    int int_Ptr[] = {5, 60, 11};
    const int* const& int_Ptr3 = int_Ptr;
    
    std::vector<int> integers3( int_Ptr3, int_Ptr3 + 0x3 );
    
    //triangles( triangles_Ptr, triangles_Ptr + size )
    
    printf("intSize: %1d int2Size: %2d int3Size: %3d\n", integers.size(), integers2.size(), integers3.size());
    for (size_t i = 0; i < integers2.size(); ++i )
    {
        printf("element %1d: %2d\n", i, integers2[i]);
    }
    
    //OrientationMatrix3f orientation( 2, 1, 3,
                                     //4, 0, 5,
                                     //3, 4, 1 );
    OrientationMatrix3f orientation( 2, 0, 0,
                                     0, 23, 0,
                                     0, 0, 8 );
    print( orientation );
    printf("magX: %1f\n", magnitude( Vector3f( orientation.Xx, orientation.Xy, orientation.Xz ) ) );
    printf("magY: %1f\n", magnitude( Vector3f( orientation.Yx, orientation.Yy, orientation.Yz ) ) );
    printf("magZ: %1f\n", magnitude( Vector3f( orientation.Zx, orientation.Zy, orientation.Zz ) ) );
    
    std::vector< GL_Trianglef* > triangles;
    std::vector< GL_Trianglef > triangles2;
    Vector3f vecA( 0.0f, 1.0f, -2.0f );
    Vector3f vecB( -1.0f, 2.0f, 2.0f );
    Vector3f vecC( 0.0f, 2.0f, 0.0f );
    Vector3f vecD( 1.0f, 2.0f, 2.0f );
    Vector3f vecE( 0.0f, 0.0f, 0.0f );
    
    Vector3f vecX( 1.0f, 0.0f, 0.0f ); // bottom-right
    Vector3f vecY( -2.0f, 1.0f, -3.0f ); // bottom-left
    Vector3f vecZ( 0.5f, 3.0f, -1.2f ); // top
    
    GL_Trianglef triW( vecE, vecY, vecX ); // bottom face
    GL_Trianglef triX( vecE, vecX, vecZ ); // right face
    GL_Trianglef triY( vecE, vecZ, vecY ); // left face
    GL_Trianglef triZ( vecY, vecZ, vecX ); // back face
    
    GL_Trianglef triA( vecA, vecB, vecC );
    GL_Trianglef triB( vecC, vecD, vecA );
    GL_Trianglef triC( vecB, vecE, vecC );
    GL_Trianglef triD( vecC, vecE, vecD );
    GL_Trianglef triE( vecA, vecD, vecE );
    GL_Trianglef triF( vecE, vecB, vecA );
    
    triangles.push_back( &triA );
    triangles.push_back( &triB );
    triangles.push_back( &triC );
    triangles.push_back( &triD );
    triangles.push_back( &triE );
    triangles.push_back( &triF );
    //triangles.push_back( &triW );
    //triangles.push_back( &triX );
    //triangles.push_back( &triY );
    //triangles.push_back( &triZ );
    
    //triangles2.push_back( triA );
    //triangles2.push_back( triB );
    //triangles2.push_back( triC );
    //triangles2.push_back( triD );
    //triangles2.push_back( triE );
    //triangles2.push_back( triF );
    triangles2.push_back( triW );
    triangles2.push_back( triX );
    triangles2.push_back( triY );
    triangles2.push_back( triZ );
    
    OrientationMatrix3f orientation2( -1.0f, 0.0f, 0.0f,
                                      0.0f, 1.0f, 0.0f,
                                      0.0f, 0.0f, -1.0f );
    
    Vector3f position( 0.0f, 0.0f, 0.0f );
    
    //OBBTreef obbtree( GL_Actor( position.x, position.y, position.z, 
    //                                       orientation2.Xx, orientation2.Yx, orientation2.Zx,
    //                                       orientation2.Xy, orientation2.Yy, orientation2.Zy,
    //                                       orientation2.Xz, orientation2.Yz, orientation2.Zz ), triangles );
    
    #define PI 3.14159265f
    orientation2.globalRotateZY( PI / 2.0f );
    print( orientation2 );
    
    GL_Objectf obj( triangles2 );

    Vector3f& pos = position;
    obj = GL_Objectf( triangles2 );
    
    OrientationMatrix3f orientation3( -1.0f, -1.0f, 8.0f,
                                      2.0f, 0.0f, 7.0f,
                                      0.0f, 5.0f, -1.0f );
    print( orientation3.getTranspose()*orientation3 );
    
    GL_MobileObjectf mobj( obj, Vector3f(1.0f, 2.0f, 1.0f) );
    mobj = obj;
    render( mobj, -1 );
    mobj.updateDisplacement( 1.0f );
    mobj.setPosition(10.0f, 21.0f, 2.0f );
    render( mobj, -1 );
    
    /*int numA = 3;
    int numB = 5;
    
    BinaryTree<int> bt;
    bt.leftChild() = &numA;
    bt.rightChild() = &numB;
    std::cout << *bt.leftChild() << " " << *bt.rightChild() << std::endl;*/
    
    //bool (*compareList[2])(const int& a, const int& b) = { introsort_ns::lessThan<int>, introsort_ns::lessThan<int> };
    
    //compareTest( compareList, 2 );

    #ifdef TEST
    Vector3f v( 1, 2, 3 );
    //OrientationMatrix3f* om = new OrientationMatrix3f();
    //GL_Actorf a = GL_Actorf();
    //GL_Trianglef tri(1, 2, 3, 3, 4, 5, 5, 6, 7);
    //GL_Objectf* o = new GL_Objectf( std::vector<GL_Trianglef> );
    Matrix3f my_mat( 1, 2, 4, 1, 1, 2, 2, 4, 1 );
    mat3 mat( vec3( 1, 2, 4 ), vec3( 1, 1, 2 ), vec3( 2, 4, 1 ) );
    size_t i( 0 );
    do
    {
        size_t j( 0 );
        do
        {
            //abs(1);
            //ABS( -1 );
            //my_fabs(-1);
            //my_mat.getInverse();
            //mat.inverse();
            //static_cast<int>(static_cast<double>(i));
            //static_cast<GLfloat>(i);
            //dynamic_cast<GL_Actorf*>(o);
            //(float)i * (float)j;
            //test1<float>();
            //normalize( v ); //
            //fabs( 1.0f );
            //i < 1.0f;
            //const_cast<const Vector3f*>(&v);
            //float e = fabs( 1.0f );
            //v.normalize();
            //v.getNormal();
            //normal( v );
            //normal( tri );
            //tri.getNormal();
            //std::max( 1, 2 );
            //( 1 > 2 ? 2 : 1 );
            ++j;
        } while ( j < 1 );
        ++i;
    } while ( i < 99999999 );
    /*std::vector<int> a;
    a.push_back(0);
    a.push_back(1);
    int& b = a[1];
    printf( "a[0] address: %1d\n", &a[0] );
    printf( "%1d\n", b );
    a.resize( 50 );
    printf( "a[0] address: %1d\n", &a[0] );
    printf( "%1d\n", b );*/
    //test_sort( introsort<int>, 10000000 );
    //test_sort( introsort<int, int>, 10000 );
    #endif // TEST

    system("PAUSE");

    return 0;
}



/*
#include <windows.h>    // Must have for Windows platform builds
#include "glee.h"       // OpenGL Extension "autoloader"
#include <gl\gl.h>      // Microsoft OpenGL headers (version 1.1 by themselves)
#include <gl\glu.h>     // OpenGL Utilities
#include "glut.h"       // OpenGL Utility Toolkit (Glut) (Free-Glut on Windows)

#include <math.h>

#include "GL_Actor.h"

#ifndef GL_PI
#define GL_PI 3.1415f
#endif // GL_PI

static GL_Actor cam; // camera

void RenderScene( void )
{
    static GLfloat angle = 0.0f;
    
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    
    glPushMatrix();
        
        cam.transformCamera();
        
        // Large sphere
        glTranslatef( 0.0f, 0.0f, -10.0f );
        glColor3f( 1.0f, 0.0f, 0.0f );
        glutWireSphere( 5.0, 50, 15 );
        
        // Rotating sphere
        glRotatef( angle, 0.0f, 1.0f, 0.5f );
        glTranslatef( 7.0f, 0.0f, 0.0f );

        glColor3f( 0.0f, 1.0f, 1.0f );
        glutSolidSphere( 1.0, 15, 15 );
        
    glPopMatrix();
    
    angle += 5.0f;
    if ( angle >= 360.f )
        angle -= 360.0f;

    glutSwapBuffers();
}

void ChangeSize( int w, int h )
{
    if ( w == 0 )
        w = 1;
    if ( h == 0 )
        h = 1;
    
    glViewport( 0, 0, w, h );
    
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    
    GLfloat aspectRatio = (GLfloat)w / (GLfloat)h;
    
    gluPerspective( 90.0, aspectRatio, 0.1, 400 );
    
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
}

void SpecialKeys( int key, int x, int y )
{
    if ( key == GLUT_KEY_UP )
        cam.moveForward( 1.0f );
    else if ( key == GLUT_KEY_DOWN )
        cam.moveForward( -1.0f );
    else if ( key == GLUT_KEY_LEFT )
        cam.rotateLeft( 0.07f );
    else if ( key == GLUT_KEY_RIGHT )
        cam.rotateLeft( -0.07f );
    
    glutPostRedisplay();
}

void TimerFunction( int timer )
{
    glutPostRedisplay();
    glutTimerFunc( timer, TimerFunction, timer );
}

void SetupRC( void )
{
    glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
    glColor3f( 1.0f, 0.0f, 0.0f );

    glShadeModel( GL_SMOOTH ); //GL_FLAT        // Sets how polygons are to be colored
    
    glFrontFace( GL_CCW );  // Front face is on the side of the polygon that is drawn counter-clockwise
    glEnable( GL_DEPTH_TEST );  // Hidden surface removal (akin to drawing polygons further away, then closest to the camera first)
    glEnable( GL_CULL_FACE );   // Enable culling faces of polygons
    glCullFace( GL_BACK );      // Do not calculate back face of polygons (akin to removing the back faces of polygons)
    
    GLfloat ambientLight[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    glEnable( GL_LIGHTING );
    glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambientLight );
    
    //GLfloat gray[] = { 1.5f, 1.5f, 1.5f, 1.0f };
    //glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gray );
    
    glEnable( GL_COLOR_MATERIAL );
    glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
}

int main( int argc, char* argv[] )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
    glutInitWindowSize( 800, 600 );
    glutCreateWindow( "Test" );
    glutReshapeFunc( ChangeSize );
    glutDisplayFunc( RenderScene );
    glutSpecialFunc( SpecialKeys );
    glutTimerFunc( 33, TimerFunction, 33 );

    SetupRC();
    glutMainLoop();
    
    return 0;
}
*/

/*
#include <windows.h>    // Must have for Windows platform builds
#include "glee.h"       // OpenGL Extension "autoloader"
#include <gl\gl.h>      // Microsoft OpenGL headers (version 1.1 by themselves)
#include <gl\glu.h>     // OpenGL Utilities
#include "glut.h"       // Glut (Free-Glut on Windows)

#include <math.h>
#include <iostream>

#include "GL_Actor.h"

#ifndef GL_PI
#define GL_PI 3.1415f
#endif // GL_PI

static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;

static GL_Actor cam;

void ChangeSize( int w, int h )
{
    if ( w == 0 )
        w = 1;
    if ( h == 0 )
        h = 1;
    
    glViewport( 0, 0, w, h );
    
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();

    GLfloat nRange = 120.0f;
    GLfloat aspectRatio = (GLfloat) w / (GLfloat) h;
    
    //if ( w > h )
    //   glOrtho( -nRange * aspectRatio, nRange * aspectRatio, -nRange, nRange, -nRange, nRange );
    //else // w <= h
    //    glOrtho( -nRange, nRange, -nRange / aspectRatio, nRange / aspectRatio, -nRange, nRange );
    
    gluPerspective( 90, aspectRatio, 0.1, 500.0 );
    
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
}

void SetupRC( void )
{
    // Light values and coordinates
    GLfloat whiteLight[] = { 0.45f, 0.45f, 0.45f, 1.0f };
    GLfloat sourceLight[] = { 0.25f, 0.25f, 0.25f, 1.0f };
    GLfloat lightPos[] = { -50.0f, 25.0f, 250.0f, 0.0f };
    
    glEnable( GL_DEPTH_TEST );  // Hidden surface removal
    glFrontFace( GL_CCW );      // Counter clock-wise polygons face out
    glEnable( GL_CULL_FACE );   // Do not calculate inside of jet
    
    // Enable lighting
    glEnable( GL_LIGHTING );
    
    // Setup and enable light 0
    glLightModelfv( GL_LIGHT_MODEL_AMBIENT, whiteLight );
    glLightfv( GL_LIGHT0, GL_AMBIENT, sourceLight );
    glLightfv( GL_LIGHT0, GL_DIFFUSE, sourceLight );
    glLightfv( GL_LIGHT0, GL_POSITION, lightPos );
    glEnable( GL_LIGHT0 );
    
    // Enable color tracking
    glEnable( GL_COLOR_MATERIAL );
    
    // Set Material properties to follow glColor values
    glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
    
    // Black blue background
    glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
}

// x and y represents the mouse pointer coordinates
void SpecialKeys( int key, int x, int y )
{
    printf("%1d %2d %3f\n", x, y, GL_PI );
    GLfloat step = 3.0f;

    if ( key == GLUT_KEY_UP )
    {
        cam.moveForward( step );
        // xRot -= 5.0f;
    }
    else if ( key == GLUT_KEY_DOWN )
    {
        cam.moveForward( -step );
        // xRot += 5.0f;
    }
    else if ( key == GLUT_KEY_LEFT )
    {
        cam.rotateLeft( 0.07f );
        // yRot -= 5.0f;
    }
    else if ( key == GLUT_KEY_RIGHT )
    {
        cam.rotateLeft( -.07f );
        //yRot += 5.0f;
    }
    
    //xRot = (GLfloat) ( static_cast<int>( xRot ) % 360 );
    //yRot = (GLfloat) ( static_cast<int>( yRot ) % 360 );
    
    glutPostRedisplay();
}

void RenderScene( void )
{
    float fZ = 100.0f, bZ = -100.0f;
    
    // Clear the window with current clearing color
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glPushMatrix();

        cam.transformCamera();
        
        glTranslatef( 0.0f, 0.0f, -200.0f );
        //glRotatef( xRot, 1.0f, 0.0f, 0.0f );
        //glRotatef( yRot, 0.0f, 1.0f, 0.0f );
        
        glColor4f( 1.0f, 0.0f, 0.0f, 1.0f );
        
        glBegin( GL_QUADS );
            // Pointing straight out Z
            glNormal3f( 0.0f, 0.0f, 1.0f );
            
            // Left Panel
            glVertex3f( -50.0f, 50.0f, fZ );
            glVertex3f( -50.0f, -50.0f, fZ );
            glVertex3f( -35.0f, -50.0f, fZ );
            glVertex3f( -35.0f, 50.0f, fZ );
            
            // Right Panel
            glVertex3f( 50.0f, 50.0f, fZ );
            glVertex3f( 35.0f, 50.0f, fZ );
            glVertex3f( 35.0f, -50.0f, fZ );
            glVertex3f( 50.0f, -50.0f, fZ );
            
            // Top Panel
            glVertex3f( -35.0f, 50.0f, fZ );
            glVertex3f( -35.0f, 35.0f, fZ );
            glVertex3f( 35.0f, 35.0f, fZ );
            glVertex3f( 35.0f, 50.0f, fZ );
            
            // Bottom Panel
            glVertex3f( -35.0f, -35.0f, fZ );
            glVertex3f( -35.0f, -50.0f, fZ );
            glVertex3f( 35.0f, -50.0f, fZ );
            glVertex3f( 35.0f, -35.0f, fZ );

            // Top length section ////////////////////////////
            // Normal points up Y axis
            glNormal3f(0.0f, 1.0f, 0.0f);
            glVertex3f(-50.0f, 50.0f, fZ);
            glVertex3f(50.0f, 50.0f, fZ);
            glVertex3f(50.0f, 50.0f, bZ);
            glVertex3f(-50.0f,50.0f,bZ);
    		
            // Bottom section
            glNormal3f(0.0f, -1.0f, 0.0f);
            glVertex3f(-50.0f, -50.0f, fZ);
            glVertex3f(-50.0f, -50.0f, bZ);
            glVertex3f(50.0f, -50.0f, bZ);
            glVertex3f(50.0f, -50.0f, fZ);

            // Left section
            glNormal3f(1.0f, 0.0f, 0.0f);
            glVertex3f(50.0f, 50.0f, fZ);
            glVertex3f(50.0f, -50.0f, fZ);
            glVertex3f(50.0f, -50.0f, bZ);
            glVertex3f(50.0f, 50.0f, bZ);

            // Right Section
            glNormal3f(-1.0f, 0.0f, 0.0f);
            glVertex3f(-50.0f, 50.0f, fZ);
            glVertex3f(-50.0f, 50.0f, bZ);
            glVertex3f(-50.0f, -50.0f, bZ);
            glVertex3f(-50.0f, -50.0f, fZ);            
        glEnd();
        
        glFrontFace( GL_CW );   // clock-wise polygons face out
        
        glBegin( GL_QUADS );
            // Back section
            // Pointing straight out Z
            glNormal3f( 0.0f, 0.0f, -1.0f );
            
            // Left Panel
            glVertex3f(-50.0f, 50.0f, bZ);
            glVertex3f(-50.0f, -50.0f, bZ);
            glVertex3f(-35.0f, -50.0f, bZ);
            glVertex3f(-35.0f,50.0f,bZ);

            // Right Panel
            glVertex3f(50.0f, 50.0f, bZ);
            glVertex3f(35.0f, 50.0f, bZ);
            glVertex3f(35.0f, -50.0f, bZ);
            glVertex3f(50.0f,-50.0f,bZ);

            // Top Panel
            glVertex3f(-35.0f, 50.0f, bZ);
            glVertex3f(-35.0f, 35.0f, bZ);
            glVertex3f(35.0f, 35.0f, bZ);
            glVertex3f(35.0f, 50.0f,bZ);

            // Bottom Panel
            glVertex3f(-35.0f, -35.0f, bZ);
            glVertex3f(-35.0f, -50.0f, bZ);
            glVertex3f(35.0f, -50.0f, bZ);
            glVertex3f(35.0f, -35.0f,bZ);
    	
            // Insides /////////////////////////////
    	    glColor3f(0.75f, 0.75f, 0.75f);

            // Normal points up Y axis
            glNormal3f(0.0f, 1.0f, 0.0f);
            glVertex3f(-35.0f, 35.0f, fZ);
            glVertex3f(35.0f, 35.0f, fZ);
            glVertex3f(35.0f, 35.0f, bZ);
            glVertex3f(-35.0f,35.0f,bZ);
    		
            // Bottom section
            glNormal3f(0.0f, 1.0f, 0.0f);
            glVertex3f(-35.0f, -35.0f, fZ);
            glVertex3f(-35.0f, -35.0f, bZ);
            glVertex3f(35.0f, -35.0f, bZ);
            glVertex3f(35.0f, -35.0f, fZ);

            // Left section
            glNormal3f(1.0f, 0.0f, 0.0f);
            glVertex3f(-35.0f, 35.0f, fZ);
            glVertex3f(-35.0f, 35.0f, bZ);
            glVertex3f(-35.0f, -35.0f, bZ);
            glVertex3f(-35.0f, -35.0f, fZ);

            // Right Section
            glNormal3f(-1.0f, 0.0f, 0.0f);
            glVertex3f(35.0f, 35.0f, fZ);
            glVertex3f(35.0f, -35.0f, fZ);
            glVertex3f(35.0f, -35.0f, bZ);
            glVertex3f(35.0f, 35.0f, bZ);
        glEnd();
        
        glFrontFace( GL_CCW );      // Counter clock-wise polygons face out
    
    glPopMatrix();
    
    glutSwapBuffers();
}

int main( int argc, char* argv[] )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
    glutInitWindowSize( 800, 600 );
    glutCreateWindow( "Orthographic Projection" );
    glutDisplayFunc( RenderScene );
    glutReshapeFunc( ChangeSize );
    glutSpecialFunc( SpecialKeys );
    
    SetupRC();
    glutMainLoop();
    
    return 0;
}
*/